#include "libPPD.h"
#include "N-Step-SCAN.h"


void switchConsola (t_NIPC paquete)
{
	switch (paquete.PayloadDescriptor)
	{
		case CABEZAL:
			info(paquete);
			break;
		case CLEAN:
			clean (paquete);
			break;
		case TRACE:
			trace (paquete);
			break;
		case EXIT:
			salir();
			break;
		default:
			break;
	}
}


void info(t_NIPC paqueteRecibido)
{
	//Imprimir en pantalla la posición actual del cabezal
	extern tCabezal cabezal;
	extern int32_t sockConsola;
	char *mensaje;
	int32_t bloquearCabezal;
	int32_t nro = 0;
	mensaje = (char *)calloc (3, sizeof(int32_t));
	int32_t sizePaquete = 3 * sizeof(int32_t) + 2;
	t_NIPC paquete;
	int32_t valorRetorno;

	bloquearCabezal = pthread_mutex_lock (&cabezal.bloqueaCabezal);
	sprintf(mensaje, "%d %d %d", cabezal.posActual.C, cabezal.posActual.H, cabezal.posActual.S);
	bloquearCabezal = pthread_mutex_unlock (&cabezal.bloqueaCabezal);

	NIPC_crearpaquete(paqueteRecibido.DescriptorID, CABEZAL, sizePaquete, mensaje, nro, &paquete);
	valorRetorno = NIPC_enviar(sockConsola, paquete);

	NIPC_destruirpaquete(&paquete);
	NIPC_destruirpaquete(&paqueteRecibido);

}


void parsearSectores(char *cadenaAseparar, int32_t *cantidad, int32_t **sectores)
{
	char *spTokenSafe;
	char *palabra;
	int32_t contador=0;
	*sectores = (int32_t *) calloc (5, sizeof(int32_t));

	palabra = (strtok_r(cadenaAseparar, " ", &spTokenSafe));
	while (palabra != NULL)
	{
		*(*sectores + contador) = atoi (palabra);
		palabra = (strtok_r(NULL, " ", &spTokenSafe));
		contador++;
	}
	*sectores = (int32_t *) realloc (*sectores, contador * sizeof(int32_t));
	*cantidad = contador;
}

void clean (t_NIPC paquete)
{
	//Limpiar los sectores seteandolos a 0
	extern t_config config;
	extern sem_t semaforoLista;
	extern int32_t sockConsola;
	t_NIPC paqueteAenviar, pack;
	int32_t sectorAescribir, valorRetorno;
	int32_t *sectores;
	int32_t cantSectores;
	parsearSectores(paquete.payload,&cantSectores, &sectores);
	sectorAescribir = sectores[0];

	char *datosEnCero;
	datosEnCero = (char *) calloc (TAMSECTOR, sizeof(int32_t));

	memset(datosEnCero,'\0',TAMSECTOR);

	while ((sectorAescribir >= sectores[0]) && (sectorAescribir <= sectores[1]))
	{
		if (strcmp(config.modoInicio, "CONNECT") == 0) //PRAID
		{
			NIPC_crearpaquete(paquete.DescriptorID, ESCRIBIRSECTOR, TAMSECTOR, datosEnCero, sectorAescribir, &pack);
			if (strcmp (config.algoritmo, "CLOOK") == 0)
			{
				planificarPedidoPRAID (pack);
				sem_post(&semaforoLista);
			}
			else if (strcmp(config.algoritmo, "NSTEPSCAN") == 0)
				planificarN_Step_SCAN_RAID (pack);
			sectorAescribir++;
		}
		else if (strcmp(config.modoInicio, "LISTEN") == 0) //PFS
		{
			NIPC_crearpaquete(paquete.DescriptorID, ESCRIBIRSECTOR, TAMSECTOR,datosEnCero, sectorAescribir, &pack);
			if (strcmp (config.algoritmo, "CLOOK") == 0)
			{
				planificarPedidoPFS(pack, sockConsola);
				sem_post(&semaforoLista);
			}
			else if (strcmp(config.algoritmo, "NSTEPSCAN") == 0)
				planificarN_Step_SCAN_PFS (pack, sockConsola);
			sectorAescribir++;
		}
	}

	char *mensaje;
	mensaje = (char *) calloc (43, sizeof(char));
	mensaje = "Se ha escrito satisfactoriamente el sector";
	int32_t tamMensaje = strlen(mensaje);

	NIPC_crearpaquete(paquete.DescriptorID, paquete.PayloadDescriptor, tamMensaje, mensaje, paquete.nroSector, &paqueteAenviar);

	valorRetorno = NIPC_enviar(sockConsola, paqueteAenviar);
	free(mensaje);
	NIPC_destruirpaquete(&paqueteAenviar);
	NIPC_destruirpaquete(&paquete);

}


void trace (t_NIPC paquete)
{
	/* Agrega a la lista de pedidos los sectores pedidos en el trace */
	extern t_config config;
	extern int32_t sockConsola;
	extern sem_t semaforoLista;
	int32_t *sectores;
	int32_t cantSectores, valorRetorno, i=0;
	t_NIPC paquetePlanificar;
	 parsearSectores(paquete.payload,&cantSectores, &sectores);
	if (strcmp(config.modoInicio, "CONNECT") == 0)
	{
		while (i < cantSectores)
		{
			printf("sector %d\n", sectores[i]);
			NIPC_crearpaquete(NULL, TRACE, 0, NULL, sectores[i], &paquetePlanificar);
			if (strcmp(config.algoritmo, "CLOOK") == 0)
				planificarPedidoPRAID(paquetePlanificar);
			else if (strcmp(config.algoritmo, "NSTEPSCAN") == 0)
				planificarN_Step_SCAN_RAID (paquetePlanificar);
			i++;
		}
		i = 0;
		if (strcmp(config.algoritmo, "CLOOK") == 0)
		{
			while (i < cantSectores)
			{
				sem_post(&semaforoLista);
				i++;
			}
		}
	}
	else if (strcmp(config.modoInicio, "LISTEN") == 0)
	{
		while (i < cantSectores)
		{
			printf("sector %d\n", sectores[i]);
			NIPC_crearpaquete(NULL, TRACE, 0, NULL, sectores[i], &paquetePlanificar);
			if (strcmp(config.algoritmo, "CLOOK") == 0)
				valorRetorno = planificarPedidoPFS(paquetePlanificar, sockConsola);
			else if (strcmp(config.algoritmo, "NSTEPSCAN") == 0)
				planificarN_Step_SCAN_PFS (paquetePlanificar, sockConsola);
			i++;
		}
		i = 0;
		if (strcmp(config.algoritmo, "CLOOK") == 0)
		{
			while (i < cantSectores)
			{
				sem_post(&semaforoLista);
				i++;
			}
		}
	}
	NIPC_destruirpaquete(&paquete);
}

void salir()
{
	extern t_log *loguear;
	extern char *archivoMapeado;
	extern pthread_mutex_t bloqueaLista;
	extern sem_t semaforoLista;

	pthread_mutex_destroy(&bloqueaLista);
	sem_destroy (&semaforoLista);

	cerrarArchivoMapeado(&archivoMapeado);
	log_destroy (loguear);

	exit (0);
}
